import { BadgeAction, BadgeNode } from "./BadgeNode";
import { Logger } from "../log/logger";
import UIUtils from "../utils/UIUtils";
import { IModule, IKey } from "../common/Common";
import { BadgeView } from "./BadgeView";
import { Fview } from "../gui/UIDefine";

export default class BadgeManage implements IModule {

    /**节点池 */
    private _badges = new Map<IKey, BadgeNode>();

    /**节点组 */
    private _badgeGropu = new Map<IKey, IKey[]>();

    /**绑定节点UI */
    private _bindViews = new Map<Fview, BadgeView>();

    /**脏节点池 */
    private _tempList = new Set<BadgeNode>();

    /**是否是数字红点 */
    private _isNumBadges: boolean;

    /**红点逻辑是否运行中 */
    private _runing: boolean;


    initialize(): void {
        this.run();
    }

    onTimeLoop(): void {

        if (!this._runing) {
            return;
        }

        let temLst = this._tempList;
        if (temLst.size <= 0) {
            return;
        }

        let change = false;
        for (let elm of temLst) {
            elm.update() && (change = true);
        }

        change && this.updateView();
        this._tempList.clear();
    }

    /**开始执行红点逻辑 */
    run(nowRun?: boolean) {
        this._runing = true;

        nowRun && this.onTimeLoop();
    }

    /**停止红点逻辑 */
    stop() {
        this._runing = false;

        this._bindViews.forEach((v, k) => {
            UIUtils.setBadge(k, false);
        })
    }

    setBadgeNumActive(isNum: boolean) {
        this._isNumBadges = isNum;
    }

    /**绑定红点监听 */
    on(type: IKey, view: Fview, caller: any, refresh: boolean = true) {

        let badgeviews = this._bindViews;
        let item = badgeviews.get(view);
        if (!item) {
            item = BadgeView.create();
            badgeviews.set(view, item);
        }

        if (item.has(type)) {
            return;
        }

        item.view = view;
        item.caller = caller;
        item.add(type);

        refresh && this.event(type);
        Logger.logBusiness({ type: type, view: view?.name }, "绑定UI:");
    }


    /**
     * 解除绑定红点监听
     * @param view 
     * @param type 不传清理view下所有绑定
     * @returns 
     */
    off(view: Fview, type?: IKey) {
        let badgeviews = this._bindViews;
        let item = badgeviews.get(view);
        if (!item) return;

        UIUtils.setBadge(item.view, false);

        Logger.logView({ view: view?.name, type: type }, "解除绑定UI:");

        if (!type) {
            badgeviews.delete(view);
            item.recover();
        } else {
            item.remove(type);
        }
    }

    /**解除绑定红点监听 */
    offAll(caller: any) {

        this._bindViews.forEach((v, k) => {
            if (v.caller === caller) {  //解除绑定  
                this._bindViews.delete(k);
                v.recover();
            }
        })
    }

    /**刷新红点 */
    event(...keyLst: IKey[]) {

        if (!this._runing) return;

        for (let k of keyLst) {
            let elm = this.getBadgeNode(k);
            if (!elm) continue;

            this._tempList.add(elm);
        }
    }


    /**注册红点 */
    regist(type: IKey, param?: BadgeAction) {
        let elm = this.getOrAdd(type);
        elm.action = param;
        elm.update();
        return elm;
    }


    /**注册红点组 */
    registGropu(type: IKey, group: IKey[], action?: BadgeAction) {

        action && this.regist(type, action);
        this._badgeGropu.set(type, group);

        group.forEach(v => this.getOrAdd(v).addGropu(type));
    }


    /**注销红点 */
    unRegist(type: IKey) {
        let elms = this._badges;
        elms.has(type) && elms.delete(type);
    }

    getBadgeNode(tyep: IKey) {
        return this._badges.get(tyep);
    }

    getValueByType(type: IKey) {

        let badges = this._badges;

        let elm = badges.get(type);
        if (elm == null) {
            return 0;
        }

        let value = elm.value;

        if (!this._badgeGropu.has(type) || (!this._isNumBadges && value > 0)) {
            return value;
        }

        let redChildList = this._badgeGropu.get(type), temp = 0;
        for (let k of redChildList) {
            temp += this.getValueByType(k);

            if (!this._isNumBadges && temp > 0) {
                return 1;
            }
        }

        return value + temp;
    }

    private updateView() {

        this._bindViews.forEach((v, k) => {

            let value = v.array.reduce<number>((p, c) => p + this.getValueByType(c), 0)
            UIUtils.setBadge(k, value > 0);
        })

    }

    private getOrAdd(type: IKey) {
        let badges = this._badges;
        let item = badges.get(type);

        if (item) {
            return item;
        }

        item = new BadgeNode();
        badges.set(type, item);
        item.key = type;
        return item;
    }
}